﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Specialized;
using PMisuseAn.io;
using PMisuseAn.behaviour.model;
using System.Globalization;

namespace PMisuseAn.util
{
    public class PolicyStatementAnalyser
    {
        private static List<Attribute> agentAttributes= MisUseAnObjectsDB.loadAgentAttributes(MainWindow.clusterName);
        List<Attribute> functionalAttributes = MisUseAnObjectsDB.loadFunctionalAttributes(MainWindow.clusterName);
        List<Attribute> environmentalAttributes = MisUseAnObjectsDB.loadEnvironmentAttributes(MainWindow.clusterName);
        List<Attribute> regulatoryAttributes = MisUseAnObjectsDB.loadRegulatoryAttributes(MainWindow.clusterName);
        List<Actor> actors = MisUseAnObjectsDB.loadAllActorsFull(MainWindow.clusterName);
        List<string> agentNames= MisUseAnObjectsDB.loadAllAgentNames(MainWindow.clusterName);
        List<string> groupNames = MisUseAnObjectsDB.loadAllGroupNamesDB(MainWindow.clusterName);
        List<string> groupFunctions= MisUseAnObjectsDB.loadAllGroupFunctions(MainWindow.clusterName);
        List<string> policyFunctions = MisUseAnObjectsDB.loadAllPolicyFunctions(MainWindow.clusterName);

        public string if_content;
        public string then_content;
        public string unless_content;

        public ListDictionary tokenisedIfContent;
        public ListDictionary tokenisedThenContent;
        public ListDictionary tokenisedUnlessContent;

         

        public PolicyStatementAnalyser()
        {
            tokenisedIfContent = new ListDictionary();
            tokenisedThenContent = new ListDictionary();
            tokenisedUnlessContent = new ListDictionary();

            //agentAttributes = MisUseAnObjectsDB.loadAgentAttributes(MainWindow.clusterName);
            //functionalAttributes = MisUseAnObjectsDB.loadFunctionalAttributes(MainWindow.clusterName);
            //environmentalAttributes = MisUseAnObjectsDB.loadEnvironmentAttributes(MainWindow.clusterName);
            //actors = MisUseAnObjectsDB.loadAllActorsFull(MainWindow.clusterName);
            //agentNames = MisUseAnObjectsDB.loadAllAgentNames(MainWindow.clusterName);
            //groupNames = MisUseAnObjectsDB.loadAllGroupNamesDB(MainWindow.clusterName);
            //groupFunctions = MisUseAnObjectsDB.loadAllGroupFunctions(MainWindow.clusterName);
        }

        public void ifThenUnlessTokenisation(string statement)
        {
            if (!statement.Equals("DO[NILL]"))
            {
                if (!statement.Contains("IF"))
                {
                    return;
                }

                string[] words1 = Regex.Split(statement, "IF");
                string _content_then_unless = words1[1];

                string[] words2 = Regex.Split(_content_then_unless, "THEN");
                if_content = words2[0];
                string _content_unless = words2[1];

                string[] words3 = Regex.Split(_content_unless, "UNLESS");                
                then_content = words3[0];

                if (words3.Count() > 1)
                {
                    unless_content = words3[1];
                }                                
                
            }
        }

        public Attribute getIfAttribute()
        {
            Attribute attribute = null;
            if (if_content != null)
            {
                string[] words21 = Regex.Split(if_content, " ");

                foreach (string word in words21)
                {
                    if (word != null || !word.Trim().Equals(""))
                    {
                        string type = getType(word);
                        if (type != null && type.Equals("attribute"))
                        {
                            bool found = false;
                            foreach (Attribute att in agentAttributes)
                            {
                                if (att.name.Equals(word))
                                {
                                    attribute = att;
                                    found = true;
                                }
                            }
                            if (!found)
                            {
                                foreach (Attribute att in regulatoryAttributes)
                                {
                                    if (att.name.Equals(word))
                                    {
                                        attribute = att;
                                        found = true;
                                    }
                                }
                            }
                            if (!found)
                            {
                                foreach (Attribute att in environmentalAttributes)
                                {
                                    if (att.name.Equals(word))
                                    {
                                        attribute = att;
                                        found = true;
                                    }
                                }
                            }

                            break;
                        }
                    }
                }
            }
            return attribute;
        }


        public void ifThenUnlessContentTokenisation(string statement)
        {
            tokenisedIfContent = new ListDictionary();
            tokenisedThenContent = new ListDictionary();
            tokenisedUnlessContent = new ListDictionary();

            ifThenUnlessTokenisation(statement);

            if (if_content != null)
            {
                int ifseq = 0;
                string[] words21 = Regex.Split(if_content, " ");

                foreach (string word in words21)
                {
                    if (word != null || !word.Trim().Equals(""))
                    {
                        string type = getType(word);
                        if (type != null)
                        {
                            Dictionary<string, string> word_m = new Dictionary<string, string>();
                            word_m.Add(type, word);
                            tokenisedIfContent.Add(ifseq, word_m);
                            ifseq = ifseq + 1;
                        }
                    }
                }
            }

            if (then_content != null)
            {
                int thenseq = 0;
                string[] words21 = Regex.Split(then_content, " ");

                foreach (string word in words21)
                {
                    if (word != null || !word.Trim().Equals(""))
                    {
                        string type = getType(word);
                        if (type != null)
                        {
                            Dictionary<string, string> word_m = new Dictionary<string, string>();
                            word_m.Add(type, word);
                            tokenisedThenContent.Add(thenseq, word_m);
                            thenseq = thenseq + 1;
                        }
                    }
                }
            }

            if (unless_content != null)
            {
                int unlessseq = 0;
                string[] words21 = Regex.Split(unless_content, " ");

                foreach (string word in words21)
                {
                    if (word != null || !word.Trim().Equals(""))
                    {
                        string type = getType(word);
                        if (type != null)
                        {
                            Dictionary<string, string> word_m = new Dictionary<string, string>();
                            word_m.Add(type, word);
                            tokenisedUnlessContent.Add(unlessseq, word_m);
                            unlessseq = unlessseq + 1;
                        }
                    }
                }
            }
        }
        public string getType(string word)
        {
            string type = null;
            
            if (word.Equals("PREVIOUSLY") ||word.Equals("EVENTUALLY")
                ||word.Equals("NEXT-TIME")||word.Equals("LAST-TIME")
                || word.Equals("ALL-TIME") || word.Equals("HENCEFORTH"))
            {                
                type = "temporalconstraint";
                return type;
            }            
            else if (word.Equals("["))
            {
                type = "openingsquarebracket";
                return type;
            }
            else if (word.Equals("]"))
            {
                type = "closingsquarebracket";
                return type;
            }
            else if (word.Equals("&lt;"))
            {
                type = "lessthan";
                return type;
            }
            else if (word.Equals(">"))
            {
                type = "greaterthan";
                return type;
            }
            else if (word.Equals("="))
            {
                type = "equals";
                return type;
            }
            else if (word.Equals("≠"))
            {
                type = "notequals";
                return type;
            }
            else if (word.Equals("⇔"))
            {
                type = "equilavence";
                return type;
            }
            else if (word.Equals("⊨"))
            {
                type = "entails";
                return type;
            }
            else if (word.Equals("⊆"))
            {
                type = "subset";
                return type;
            }
            else if (word.Equals("⊂"))
            {
                type = "entails";
                return type;
            }
            else if (word.Equals("∪"))
            {
                type = "union";
                return type;
            }
            else if (word.Equals("∩"))
            {
                type = "intersection";
                return type;
            }
            else if (word.Equals("∈"))
            {
                type = "elementOf";
                return type;
            }
            else if (word.Equals("∉"))
            {
                type = "notElementof";
                return type;
            }
            else if (word.Equals("¬"))
            {
                type = "not";
                return type;
            }
            else if (word.Equals("→"))
            {
                type = "implies";
                return type;
            }
            else if (word.Equals("V"))
            {
                type = "or";
                return type;
            }
            else if (word.Equals("∧"))
            {
                type = "and";
                return type;
            }                      
            else if (word.Equals("("))
            {
                type = "openingBracket";
                return type;
            }
            else if (word.Equals(")"))
            {
                type = "closingBracket";
                return type;
            }
            else if (word.Equals("+"))
            {
                type = "plus";
                return type;
            }
            else if (word.Equals(","))
            {
                type = "comma";
                return type;
            }
            else if (word.Equals("-"))
            {
                type = "minus";
                return type;
            }
            else if (word.Equals("*"))
            {
                type = "multiplication";
                return type;
            }
            else if (word.Equals("/"))
            {
                type = "division";
                return type;
            }

            else if (word.Equals("sender"))
            {
                type = "sender";
                return type;
            }
            else if (word.Equals("receiver"))
            {
                type = "receiver";
                return type;
            }
            else if (word.Equals("subject"))
            {
                type = "subject";
                return type;
            }
            

            foreach (Attribute att in agentAttributes)
            {
                if (att.name.Equals(word))
                {
                    type = "attribute";
                    return type;
                }
            }

            foreach (Attribute att in regulatoryAttributes)
            {
                if (att.name.Equals(word))
                {
                    type = "attribute";
                    return type;
                }
            }

            foreach (Attribute att in functionalAttributes)
            {
                if (att.name.Equals(word))
                {
                    type = "functionalAttribute";
                    return type;
                }
            }

            foreach (Attribute att in environmentalAttributes)
            {
                if (att.name.Equals(word))
                {
                    type = "attribute";
                    return type;
                }
            }

            foreach (string policyFunction in policyFunctions)
            {
                if (policyFunction.Equals(word))
                {
                    type = "policyFunction";
                    return type;
                }
            } 

            foreach (string groupFunction in groupFunctions)
            {
                if (groupFunction.Equals(word))
                {
                    type = "groupFunction";
                    return type;
                }
            } 


            //foreach (Actor actor in actors)
            //{
            //    foreach (string role in actor.roles)
            //    {
            //        if (role.Equals(word))
            //        {
            //            type = "actorRole";
            //            return type;
            //        }
            //    }                
            //}

            foreach (string agent in agentNames)
            {
                if (agent.Equals(word))
                {
                    type = "agent";
                    return type;
                }
            }

            foreach (string group in groupNames)
            {
                if (group.Equals(word))
                {
                    type = "group";
                    return type;
                }
            }

            double number;

            if (Double.TryParse(word, out number))
            {
                type = "number";
                return type;
            }
            else if(word.Trim().TrimEnd().TrimStart().Count()>0)
            {
                type = "string";
                return type;
            }

            return type;
        }
    }
}
